/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.address;

import javax.sip.address.TelURL;
import java.text.ParseException;

/**
 * This class represents Tel URLs, which are used for addressing. The Tel URL
 * starts with the scheme <code>tel:</code>. This tells the
 * local entity that what follows is a URL that should be parsed as described
 * in <a href = "http://www.ietf.org/rfc/rfc2806.txt">RFC2806</a>. After that,
 * the URL contains the phone number of the remote entity.
 * <p/>
 * Within a SIP Message, TelURLs can be used to indicate the source and intended
 * destination of a Request, redirection addresses and the current destination
 * of a Request. All these Headers may contain TelURLs.
 * <p/>
 * The TelURL interface extends the generic URI interface and provides
 * additional convenience methods for the following components of a TelURL
 * address, above the generic URI class:
 * <ul>
 * <li>ISDN Subaddress - Phone numbers can also contain subaddresses, which
 * are used to identify different remote entities under the same phone number.
 * <li>Post Dial - Phone numbers can also contain a post-dial sequence.
 * This is what is often used with voice mailboxes and other services that
 * are controlled by dialing numbers from your phone keypad while the call is
 * in progress.
 * <li>Global - Phone numbers can be either "global" or "local". Global numbers
 * are unambiguous everywhere. Local numbers are usable only within a certain
 * area.
 * <li>URL parameters - Parameters affecting a request constructed from this
 * URL. URL parameters are added to the end of the URL component and are
 * separated by semi-colons. URL parameters take the form:<br>
 * parameter-name "=" parameter-value
 * </ul>
 * See <a href = "http://www.ietf.org/rfc/rfc2806.txt">RFC2806</a> for more
 * information on the use of TelURL's.
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class TelURLImpl extends URIBase implements TelURL {
    private boolean isGlobal = false;
    private String phoneNumber;

    private final static TelURLParser parser = new TelURLParser();

    public TelURLImpl() {
        super("tel");
    }

    public TelURLImpl(String phoneNumber) {
        super("tel");
        if (phoneNumber.startsWith("+")) {
            isGlobal = true;
            phoneNumber = phoneNumber.substring(1);
        }
        this.phoneNumber = phoneNumber;
    }

    protected URIParser getParser() {
        return parser;
    }

    public Object clone() {
        final TelURLImpl uri = new TelURLImpl();
        uri.cloneInternals(this);
        if (parsed) {
            uri.isGlobal = this.isGlobal;
            uri.phoneNumber = this.phoneNumber;
        }
        return uri;
    }

    /**
     * This method determines if this is a URI with a scheme of "sip" or "sips".
     *
     * @return <code>true</code> if the scheme is "sip" or "sips", <code>false</code> otherwise.
     */
    public final boolean isSipURI() {
        return false;
    }

    /**
     * Returns <code>true</code> if this TelURL is global i.e. if the TelURI
     * has a global phone user.
     *
     * @return <code>true</code> if this TelURL represents a global phone user,
     *         and <code>false</code> otherwise.
     */
    public boolean isGlobal() {
        parse();
        return isGlobal;
    }

    /**
     * Sets phone user of this TelURL to be either global or local. The default
     * value is false, hence the TelURL is defaulted to local.
     *
     * @param global the boolean value indicating if the TelURL has a global
     *               phone user.
     */
    public void setGlobal(boolean global) {
        invalidateStringValue();
        this.isGlobal = global;
    }

    /**
     * Sets post dial of this TelURL. The post-dial sequence describes what and
     * when the local entity should send to the phone line.
     *
     * @param postDial new value of the <code>postDial</code> parameter.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the postDial value.
     */
    public void setPostDial(String postDial) throws ParseException {
        setParameter("postd", postDial);
    }

    /**
     * Returns the value of the <code>postDial</code> parameter, or null if it
     * is not set.
     *
     * @return the value of the <code>postDial</code> parameter.
     */
    public String getPostDial() {
        return getParameter("postd");
    }

    /**
     * Sets phone number of this TelURL. The phone number may either be local or
     * global determined by the isGlobal method in this interface. The phoneNumber
     * argument should not contain the "+" associated with telephone numbers.
     *
     * @param phoneNumber - new value of the <code>phoneNumber</code> parameter
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the phoneNumber value.
     */
    public void setPhoneNumber(String phoneNumber) throws ParseException {
        invalidateStringValue();
        this.phoneNumber = phoneNumber;
    }

    /**
     * Returns the value of the <code>phoneNumber</code> parameter. This method
     * will not return the "+" associated with telephone numbers.
     *
     * @return the value of the <code>phoneNumber</code> parameter
     */
    public String getPhoneNumber() {
        parse();
        return phoneNumber;
    }

    /**
     * Sets ISDN subaddress of this TelURL. If a subaddress is present, it is
     * appended to the phone number after ";isub=".
     *
     * @param isdnSubAddress new value of the <code>isdnSubAddress</code>
     *                       parameter.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the isdnSubAddress value.
     */
    public void setIsdnSubAddress(String isdnSubAddress) throws ParseException {
        setParameter("isub", isdnSubAddress);
    }

    /**
     * Returns the value of the <code>isdnSubAddress</code> parameter, or null
     * if it is not set.
     *
     * @return the value of the <code>isdnSubAddress</code> parameter
     */
    public String getIsdnSubAddress() {
        return getParameter("isub");
    }

    /**
     * Sets the phone context of this TelURL.
     *
     * @param phoneContext new value of the <code>phoneContext</code>
     *                     parameter.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the phoneContext value.
     */
    public void setPhoneContext(String phoneContext) throws ParseException {
        setParameter("phone-context", phoneContext);
    }

    /**
     * Returns the value of the <code>phoneContext</code> parameter, or null
     * if it is not set.
     *
     * @return the value of the <code>phoneContext</code> parameter.
     */
    public String getPhoneContext() {
        return getParameter("phone-context");
    }

    protected String buildStringValue() {
        final StringBuilder sb = new StringBuilder();
        sb.append(getScheme()).append(':');
        if (isGlobal) sb.append('+');
        sb.append(phoneNumber);
        sb.append(getParametersAsString(";"));
        return sb.toString();
    }

    protected static TelURLImpl createLazily(String url) {
        return createLazily(url.getBytes(), 0, url.length());
    }

    protected static TelURLImpl createLazily(byte[] data, int start, int end) {
        final TelURLImpl uri = new TelURLImpl();
        uri.data = data;
        uri.start = start;
        uri.end = end;
        uri.parsed = false;
        return uri;
    }
}
/*
 * $Log$
 */